home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / program / palis102.lha / Palis / cdxMakePatches / cdxMakePatches.c next >
C/C++ Source or Header  |  1992-09-02  |  5KB  |  248 lines

  1. /*
  2.     ·C·O·D·E·X· ·D·E·S·I·G·N· ·S·O·F·T·W·A·R·E·
  3.     presents:
  4.  
  5.      cdxMakePatches.c
  6.  
  7.     How to savely install / remove several patches.
  8.  
  9.     - Supports _all_ patch managers.
  10.     - Supports dummy code if none is found.
  11.     - Supports use of semaphores in order to avoid that another
  12.       task runs your code.
  13.  
  14.     (c)by Hans Bühler
  15. */
  16.  
  17. #include    "cdxMakePatches.h"
  18.  
  19. // ------------------------------------
  20. // defines (internal)
  21. // ------------------------------------
  22.  
  23. #define    JMP_CODE                0x4ef9
  24.  
  25. #define    STATUS_OK            0
  26. #define    STATUS_FORCE        1
  27. #define    STATUS_ERROR        2
  28.  
  29. // ------------------------------------
  30. // datatypes (internal)
  31. // ------------------------------------
  32.  
  33. struct ForceCode
  34.     {
  35.         UWORD                        Jmp;            // jmp code (0x4ef9)
  36.         APTR                        Adr;            // address to jump (==NewFunc)
  37.     };
  38.  
  39. struct cdxPatch
  40.     {
  41.         struct cdxPatch            *Next,*Prev;
  42.  
  43.         struct Library                *Lib;
  44.         WORD                            Offset;
  45.         APTR                            NewFunc,OldFunc;
  46.  
  47.         APTR                            Dummy;
  48.  
  49.         struct ForceCode            *ForceCode;
  50.         struct SignalSemaphore    *Sem;
  51.     };
  52.  
  53. // ------------------------------------
  54. // vars
  55. // ------------------------------------
  56.  
  57. // ------------------------------------
  58. // funx
  59. // ------------------------------------
  60.  
  61. /*********************************************
  62.  * this func installs some functions to libs *
  63.  * returns ptr to old function or NULL            *
  64.  * REMEMBER TO INITIALIZE THE HEADPTR BY ZERO*
  65.  * BEFORE INSTALLING THE FIRST PTR !!            *
  66.  *********************************************/
  67.  
  68. APTR __asm cdxPutFunction(register __a0 APTR *headPtr,
  69.                           register __d0 UWORD Flags,
  70.                           register __a1 APTR lib,
  71.                           register __d1 WORD offset,
  72.                           register __a2 APTR newFunc)
  73. {
  74.     struct cdxPatch    *patch;
  75.  
  76.     if(!headPtr)
  77.         return 0;
  78.  
  79.     if(!( patch = AllocVec(sizeof(struct cdxPatch), MEMF_PUBLIC|MEMF_CLEAR) ))
  80.         return 0;
  81.  
  82.     patch->Lib        =    lib;
  83.     patch->Offset    =    offset;
  84.     patch->NewFunc    =    newFunc;
  85.  
  86.     if(Flags & CDXFUNCF_ADDSEM)
  87.     {
  88.         if(!( patch->Sem = AllocVec(sizeof(struct SignalSemaphore), MEMF_PUBLIC|MEMF_CLEAR) ))
  89.         {
  90.             FreeVec(patch);
  91.             return 0;
  92.         }
  93.  
  94.         InitSemaphore(patch->Sem);
  95.     }
  96.  
  97.     // -- check additional flags --
  98.  
  99.     if(Flags & CDXFUNCF_ADDCODE)
  100.     {
  101.         if(!( patch->ForceCode = AllocVec(sizeof(struct ForceCode), MEMF_PUBLIC) ))
  102.         {
  103.             if(patch->Sem)
  104.                 FreeVec(patch->Sem);
  105.             FreeVec(patch);
  106.             return 0;
  107.         }
  108.  
  109.         patch->ForceCode->Jmp    =    JMP_CODE;
  110.         patch->ForceCode->Adr    =    patch->NewFunc;
  111.         newFunc                        =    patch->ForceCode;
  112.     }
  113.  
  114.     // -- set new function --
  115.  
  116.     patch->OldFunc    =    SetFunction(lib,offset,newFunc);
  117.  
  118.     if(patch->Next = *headPtr)
  119.         patch->Next->Prev    =    patch;
  120.     *headPtr    =    patch;
  121.  
  122.     return patch->OldFunc;
  123. }
  124.  
  125. /*********************************************
  126.  * this func tries to remove these functions    *
  127.  * and will savely keep all installed if it    *
  128.  * wasn't possible to remove _ALL_                *
  129.  * returns FALSE if de-installation failed.    *
  130.  * Save to be called after failure from        *
  131.  * cdxPutLibFunction()                                *
  132.  *********************************************/
  133.  
  134. BOOL __asm cdxRemAllFunctions(register __a0 APTR *headPtr,
  135.                               register __d0 BOOL force)
  136. {
  137.     struct cdxPatch    *patch,*next;
  138.     UBYTE                    status;
  139.     BOOL                    ok;
  140.  
  141.     Forbid();
  142.  
  143.     CacheClearU();
  144.  
  145.     status    =    STATUS_OK;
  146.  
  147.     for(patch = *headPtr; patch; patch = patch->Next)
  148.     {
  149.         patch->Dummy    =    SetFunction(patch->Lib,patch->Offset,patch->OldFunc);
  150.  
  151.         if(patch->ForceCode)
  152.         {
  153.             if(patch->Dummy != patch->ForceCode)
  154.                 status    =    force ? STATUS_FORCE : STATUS_ERROR;    // this is difficult but okay at all
  155.         }
  156.         else
  157.             if(patch->Dummy != patch->NewFunc)
  158.                 status    =    STATUS_ERROR;
  159.  
  160.         if(status == STATUS_ERROR)
  161.             break;                            // note: patch != 0 !!!!
  162.     }
  163.  
  164.     // -- check whether there had been problems --
  165.  
  166.     if(status == STATUS_ERROR)
  167.     {
  168.         for(; patch; patch = patch->Prev)
  169.             SetFunction(patch->Lib,patch->Offset,patch->Dummy);    // back to life
  170.  
  171.         ok    =    FALSE;                        // ;-O
  172.  
  173.         Permit();
  174.     }
  175.     else
  176.     {
  177.         // first, restore FORCEed patches
  178.  
  179.         if(status == STATUS_FORCE)        // all patches had been checked !
  180.             for(patch = *headPtr; patch; patch = patch->Next)
  181.             {
  182.                 if(patch->ForceCode && (patch->Dummy != patch->ForceCode))
  183.                 {
  184.                     patch->ForceCode->Adr    =    patch->OldFunc;
  185.                     patch->ForceCode            =    0;
  186.                     SetFunction(patch->Lib,patch->Offset,patch->Dummy);
  187.                 }
  188.             }
  189.  
  190.         // free unused memory
  191.  
  192.         Permit();
  193.  
  194.         next    =    *headPtr;
  195.  
  196.         while(patch = next)
  197.         {
  198.             next    =    patch->Next;
  199.  
  200.             if(patch->Sem)
  201.             {
  202.                 ObtainSemaphore(patch->Sem);        // exclusive access
  203.                 ReleaseSemaphore(patch->Sem);
  204.                 FreeVec(patch->Sem);
  205.             }
  206.  
  207.             if(patch->ForceCode)
  208.                 FreeVec(patch->ForceCode);
  209.             FreeVec(patch);
  210.         }
  211.  
  212.         *headPtr    =    0;
  213.  
  214.         ok    =    TRUE;
  215.     }
  216.  
  217.     return ok;
  218. }
  219.  
  220. // ------------------------------------
  221. // help stuff
  222. // ------------------------------------
  223.  
  224. /************************************************************
  225.  * This function returns the SignalSemaphore allocated for    *
  226.  * "newFunc" or if newFunc is NULL of the last function.        *
  227.  * Note that NULL will be returned if the specified func        *
  228.  * doesn't had ADDFUNCF_ADDSEM flag set !                            *
  229.  ************************************************************/
  230.  
  231. struct SignalSemaphore *__asm cdxGetPatchSem(register __a0 APTR *headPtr,
  232.                                                           register __a1 APTR newFunc)
  233. {
  234.     struct cdxPatch    *patch;
  235.  
  236.     if(!( patch = *headPtr ))
  237.         return 0;
  238.     if(!newFunc)
  239.         return patch->Sem;
  240.  
  241.     for(; patch; patch = patch->Next)
  242.         if(patch->NewFunc == newFunc)
  243.             return patch->Sem;
  244.  
  245.     return 0;
  246. }
  247.  
  248.